﻿using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Runtime.Serialization;
using System.Text;
using System.Threading.Tasks;
using Microsoft.TeamFoundation.Client;
using Microsoft.TeamFoundation.WorkItemTracking.Client;
using UCL.Powersource.Analysis;

namespace UCL.Powersource.Statistics
{
    /// <summary>
    /// Statistic related to the number of Invalid tasks which are those 
    /// who either:
    ///  - do not have a backlog item as a parent, or;
    ///  - do not have any action assigned (they do not have an activity)
    /// </summary>
    [Export(typeof(IStatistic))]
    [DataContract(IsReference = true)]
    public class InvalidTasks : LinksRelatedWIStatisticsBase
    {
        [ExcludeFromCodeCoverage]
        public override string Label
        {
            get { return "Invalid Tasks"; }
        }

        [ExcludeFromCodeCoverage]
        public override string Description
        {
            get { return "Number of Invalid Tasks in an iteration"; }
        }

        [ExcludeFromCodeCoverage]
        public override string Name
        {
            get { return "InvalidTasks"; }
        }

        public static readonly Guid CN_Statistic_Guid = new Guid("AB3E4772-9C9A-4319-88CD-EE37CE67FF6B");
        [ExcludeFromCodeCoverage]
        public override Guid Statistic_Guid
        {
            get { return CN_Statistic_Guid; }
        }

        private string TasksWithoutAction { get { return _TasksWithoutAction; } }

        private string ParentlessTasks { get { return _ParentlessTasks; } }

        /// <summary>
        /// Class for invalid work item calculation
        /// </summary>
        /// <param name="collUri">Tfs stat project collection</param>
        /// <param name="iteration">Work item iteration</param>
        /// <param name="finishDate">Finish date</param>
        /// <param name="wiStore">Work item store</param>
        /// <returns>the number of invalid work items</returns>
        protected override int? CountInvalidWI(string collUri, string iteration, DateTime finishDate, WorkItemStore wiStore)
        {
            if (!collectionCache.ContainsKey(collUri))
            {
                collectionCache.Add(collUri, new Dictionary<string, Dictionary<string, Dictionary<DateTime, WorkItemCollection>>>());
                collectionCache[collUri].Add(iteration, new Dictionary<string, Dictionary<DateTime, WorkItemCollection>>());
                collectionCache[collUri][iteration].Add("TasksWithoutAction", new Dictionary<DateTime, WorkItemCollection>());
            }
            else if (!collectionCache[collUri].ContainsKey(iteration))
            {
                collectionCache[collUri].Add(iteration, new Dictionary<string, Dictionary<DateTime, WorkItemCollection>>());
                collectionCache[collUri][iteration].Add("TasksWithoutAction", new Dictionary<DateTime, WorkItemCollection>());
            }

            if (!linksCollectionCache.ContainsKey(collUri))
            {
                linksCollectionCache.Add(collUri, new Dictionary<string, Dictionary<string, Dictionary<DateTime, WorkItemLinkInfo[]>>>());
                linksCollectionCache[collUri].Add(iteration, new Dictionary<string, Dictionary<DateTime, WorkItemLinkInfo[]>>());
                linksCollectionCache[collUri][iteration].Add("ParentlessTasks", new Dictionary<DateTime, WorkItemLinkInfo[]>());
            }
            else if (!linksCollectionCache[collUri].ContainsKey(iteration))
            {
                linksCollectionCache[collUri].Add(iteration, new Dictionary<string, Dictionary<DateTime, WorkItemLinkInfo[]>>());
                linksCollectionCache[collUri][iteration].Add("ParentlessTasks", new Dictionary<DateTime, WorkItemLinkInfo[]>());
            }

            List<int> wiList = new List<int>();

            queryLinkResults = GetQueryLinkResults(ParentlessTasks, collUri, finishDate,iteration, wiStore, "ParentlessTasks");
            wiList.AddRange(GetListOfIds(false, true, wiStore, iteration));

            queryResults = GetQueryResults(TasksWithoutAction, collUri, finishDate,iteration, wiStore, "TasksWithoutAction");
            wiList.AddRange(GetListOfIds(false, false, wiStore, iteration));

            return wiList.Select(p => p).Distinct().Count();
        }
        
        /// <summary>
        /// Class for parentless tasks
        /// </summary>
        [DataMember]
        private string _ParentlessTasks =
                "SELECT [Id] " +
                "FROM WorkItemLinks " +
                "WHERE ([Source].[System.WorkItemType] = 'Task'  " +
                "AND [Source].[State] <> 'Removed') " +
                "And ([System.Links.LinkType] ='System.LinkTypes.Hierarchy-Reverse') " +
                "And ([Target].[System.WorkItemType] = 'Product Backlog Item') " +
                "mode(DoesNotContain) AsOf @AsOf";

        /// <summary>
        /// Class for tasks without action
        /// </summary>
        [DataMember]
        private string _TasksWithoutAction =
                "SELECT [Id], [Iteration Path] " +
                "FROM WorkItems " +
                "WHERE [Work Item Type] = 'Task'  " +
                "AND  [State] <> 'Removed' " +
                "AND [Activity] = '' " +
                "ORDER BY [Id] AsOf @AsOf";

    }
}
